﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// Convert类型扩展方法类
    /// </summary>
    public static partial class ConvertEx
    {

        private static Dictionary<PrimitiveDataTypes, ITypeConverter> _typeConverterDic = null;
        private static void InitTypeConverter()
        {
            _typeConverterDic = new Dictionary<PrimitiveDataTypes, ITypeConverter>()
            {
                { PrimitiveDataTypes.BoolType,new BooleanTypeConverter() },
                { PrimitiveDataTypes.CharType,new CharTypeConverter() },
                { PrimitiveDataTypes.ByteType,new ByteTypeConverter() },
                { PrimitiveDataTypes.SByteType,new SByteTypeConverter() },
                { PrimitiveDataTypes.Int16Type,new Int16TypeConverter() },

                { PrimitiveDataTypes.UInt16Type ,new UInt16TypeConverter() },
                { PrimitiveDataTypes.Int32Type,new Int32TypeConverter() },
                { PrimitiveDataTypes.UInt32Type,new UInt32TypeConverter() },
                { PrimitiveDataTypes.Int64Type,new Int64TypeConverter() },
                { PrimitiveDataTypes.UInt64Type,new UInt64TypeConverter() },

                { PrimitiveDataTypes.Int128Type,new Int128TypeConverter() },
                { PrimitiveDataTypes.UInt128Type,new UInt128TypeConverter() },
                { PrimitiveDataTypes.BigIntegerType,new BigIntegerTypeConverter() },
                { PrimitiveDataTypes.FloatType,new SingleTypeConverter() },                
                { PrimitiveDataTypes.DoubleType,new DoubleTypeConverter() },

                { PrimitiveDataTypes.HalfType,new HalfTypeConverter() },
                { PrimitiveDataTypes.DecimalType,new DecimalTypeConverter() },
                { PrimitiveDataTypes.DateTimeType,new DateTimeTypeConverter() },
                { PrimitiveDataTypes.TimeSpanType,new TimeSpanTypeConverter() },
                { PrimitiveDataTypes.DateTimeOffsetType,new DateTimeOffsetTypeConverter() },

                { PrimitiveDataTypes.TimeOnlyType,new TimeOnlyTypeConverter() },
                { PrimitiveDataTypes.DateOnlyType,new DateOnlyTypeConverter() },
                { PrimitiveDataTypes.StringType,new StringTypeConverter() },
                //{ PrimitiveTypes.ObjectType,new BooleanTypeConverter() },
                //{ PrimitiveTypes.GuidType,new BooleanTypeConverter() },
                //{ PrimitiveTypes.ByteAarrayType,new BooleanTypeConverter() },
                //{ PrimitiveTypes.ShortAarrayType,new BooleanTypeConverter() },
                //{ PrimitiveTypes.FloatAarrayType,new BooleanTypeConverter() },
                //{ PrimitiveTypes.Int32AarrayType,new BooleanTypeConverter() },
            };
        }

        private static bool TryGetTypeConverter(PrimitiveDataTypes converterType, out ITypeConverter targetConverter)
        {
            if (_typeConverterDic == null)
            {
                InitTypeConverter();
            }

            return _typeConverterDic.TryGetValue(converterType, out targetConverter);
        }



        /// <summary>
        /// 将value转换为T类型
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="value">待转换的值</param>
        /// <param name="targetType">目标转换类型</param>
        /// <param name="options">转换选项</param>
        /// <returns>转换新福克斯</returns>
        /// <exception cref="ArgumentNullException">options为null将抛出异常</exception>
        /// <exception cref="ArgumentException">目标类型转换器不存在异常</exception>
        public static T ConvertTo<T>(object value, PrimitiveDataTypes targetType, ITypeConverterOptions options = null)
        {
            return (T)ConvertTo(value, targetType, options);
        }

        /// <summary>
        /// 将value转换为T类型
        /// </summary>
        /// <param name="value">待转换的值</param>
        /// <param name="targetType">目标转换类型</param>
        /// <param name="options">转换选项</param>
        /// <returns>转换新福克斯</returns>
        /// <exception cref="ArgumentNullException">options为null将抛出异常</exception>
        /// <exception cref="ArgumentException">目标类型转换器不存在异常</exception>
        public static object ConvertTo(object value, PrimitiveDataTypes targetType, ITypeConverterOptions options = null)
        {
            if (TryGetTypeConverter(targetType, out var targetConverter))
            {
                return targetConverter.ConvertTo(options, value);
            }
            else
            {
                throw new ArgumentException($"目标类型\"{EnumParserManager.PrimitiveTypesEnumParser.GetEnumString(targetType)}\"对应的转换器不存在,转换失败");
            }
        }



        /// <summary>
        /// 尝试将value转换为T类型[转换成功返回true,失败返回false]
        /// </summary>
        /// <typeparam name="T">目标类型</typeparam>
        /// <param name="value">待转换的值</param>
        /// <param name="targetType">目标转换类型</param>
        /// <param name="result">转换新福克斯</param>
        /// <param name="options">转换选项</param>
        /// <returns>转换成功返回true,失败返回false</returns>
        /// <exception cref="ArgumentNullException">options为null将抛出异常</exception>
        /// <exception cref="ArgumentException">目标类型转换器不存在异常</exception>
        public static bool TryConvertTo<T>(object value, PrimitiveDataTypes targetType, out T result, ITypeConverterOptions options = null)
        {
            return TryConvertTo(value, targetType, out result, options);
        }

        /// <summary>
        /// 尝试将value转换为T类型[转换成功返回true,失败返回false]
        /// </summary>
        /// <param name="value">待转换的值</param>
        /// <param name="targetType">目标转换类型</param>
        /// <param name="result">转换新福克斯</param>
        /// <param name="options">转换选项</param>
        /// <returns>转换成功返回true,失败返回false</returns>
        /// <exception cref="ArgumentNullException">options为null将抛出异常</exception>
        /// <exception cref="ArgumentException">目标类型转换器不存在异常</exception>
        public static bool TryConvertTo(object value, PrimitiveDataTypes targetType, out object result, ITypeConverterOptions options = null)
        {
            if (TryGetTypeConverter(targetType, out var targetConverter))
            {
                object obj;
                bool ret = targetConverter.TryConvertTo(options, value, out obj);
                if (ret)
                {
                    result = obj;
                }
                else
                {
                    result = null;
                }

                return ret;
            }
            else
            {
                throw new ArgumentException($"目标类型\"{EnumParserManager.PrimitiveTypesEnumParser.GetEnumString(targetType)}\"对应的转换器不存在,转换失败");
            }
        }


    }
}
